// Learn TypeScript:
//  - https://docs.cocos.com/creator/2.4/manual/en/scripting/typescript.html
// Learn Attribute:
//  - https://docs.cocos.com/creator/2.4/manual/en/scripting/reference/attributes.html
// Learn life-cycle callbacks:
//  - https://docs.cocos.com/creator/2.4/manual/en/scripting/life-cycle-callbacks.html

import CombatComponent from "../Combats/CombatComponent";
import GameEvent from "../Commons/GameEvent";
import { CharacterDirection, CharacterType, SkillIdCenter } from "../Enums/GameEnum";
import { randomRange } from "../GlobalFunction";
import AudioManager, { AudioEffectType } from "../Managers/AudioManager";
import GameManager, { GameModel } from "../Managers/GameManager";
import PoolManager from "../Managers/PoolManager";
import SaveManager from "../Managers/SaveManager";
import TipsTxtManager from "../Managers/TipsTxtManager";
import CardManager from "../Models/Cards/CardManager";
import CharacterEntity from "../Models/Characters/CharacterEntity";
import SkillManager from "../Models/Skills/SkillManager";
import TaskManager from "../Models/Tasks/TaskManager";
import CharacterAttribute from "./CharacterAttribute";
import BaseAttackState from "./States/BaseAttackState";
import BaseIdleState from "./States/BaseIdleState";
import { BaseRunState } from "./States/BaseRunState";
import BaseState from "./States/BaseState";

const { ccclass, property } = cc._decorator;

@ccclass
export default class BaseCharacterElement extends cc.Component {

    @property({ type: cc.Enum(CharacterType) })
    public characterType: CharacterType = CharacterType.player;

    public rb2d: cc.RigidBody = null;
    public collider2d: cc.PhysicsCollider = null;
    public characterAnim: cc.Animation = null;
    public sketonAnim: sp.Skeleton;
    hpTxt: cc.Label = null;
    hpProgressbar: cc.ProgressBar = null;

    public pathIndex: number = 1;
    public pathArr: cc.Vec2[] = null;
    public direction: CharacterDirection = CharacterDirection.right;
    public attribute: CharacterAttribute;
    public currentState: BaseState;
    public idleState: BaseIdleState;
    public runState: BaseRunState;
    public attackState: BaseAttackState;
    public isCollidePlatform: boolean;
    public hurtBloodCd: number = 0;
    public isApplyLinearImpulse: boolean = false;
    characterEy: CharacterEntity = null;


    protected onLoad(): void {
        this.rb2d = this.getComponent(cc.RigidBody);
        this.collider2d = this.getComponent(cc.PhysicsCollider);
        this.characterAnim = this.getComponentInChildren(cc.Animation);
        this.sketonAnim = this.getComponentInChildren(sp.Skeleton);
        this.direction = CharacterDirection.right;
        this.attribute = new CharacterAttribute();
        this.hpTxt = this.getComponentInChildren(cc.Label);
        this.hpProgressbar = this.getComponentInChildren(cc.ProgressBar);

        this.node.on(cc.Node.EventType.TOUCH_START, this.onTouchStart, this);
    }

    protected start(): void {

        this.initState();
    }

    protected onEnable(): void {
        this.pathArr = this.getPathPosArr();

    }

    protected onDisable(): void {

    }
    onTouchStart() {
        // this.rb2d.applyLinearImpulse(cc.v2(-1000, 1000), this.rb2d.getWorldCenter(), false);
    }
    onBeginContact(contact, selfCollider: cc.Collider, otherCollider: cc.Collider): void {
        // console.log("开始碰撞");

        var otherEle = otherCollider.getComponent(BaseCharacterElement);
        this.isApplyLinearImpulse = false;
        if (otherEle == null) {
            this.isCollidePlatform = true;
        } else {
            this.isCollidePlatform = true;
            if (this.characterType == CharacterType.player) {
                this.attackState.animCaller = this;
                this.attackState.animCompleate = () => {
                    this.isApplyLinearImpulse = true;
                    this.rb2d.linearVelocity = cc.Vec2.ZERO;
                    this.rb2d.applyLinearImpulse(cc.v2(500 * this.direction * -1, 500), this.rb2d.getWorldCenter(), false);
                    this.collider2d.enabled = false;
                    this.hurtBlood(otherEle.attack, otherEle);//受到敌人攻击
                    // AudioManager.single.playEffect(AudioEffectType.hit);
                    var ackNum = this.attack;
                    if (this.characterType == CharacterType.player) {
                        if (SkillManager.single.isUnlockSkill(SkillIdCenter.id_1013)) {
                            var ey = SkillManager.single.getSkillEntity(SkillIdCenter.id_1013);
                            var random = randomRange(1, 10000);
                            if (random <= ey.valueNum * 100) {
                                ackNum *= 5;
                                TipsTxtManager.single.showCombatTxt("会心一击", cc.v2(this.node.x, this.node.y + this.node.height * 0.5),
                                    this.node.parent, cc.Color.BLUE);
                            }
                        }
                    }

                    otherEle.hurtBlood(ackNum, this);//攻击敌人
                    if (this.characterType == CharacterType.player) {
                        if (SkillManager.single.isUnlockSkill(SkillIdCenter.id_1011)) {
                            var ey = SkillManager.single.getSkillEntity(SkillIdCenter.id_1011);
                            var random = randomRange(1, 10000);
                            if (random <= ey.valueNum * 100) {
                                otherEle.hurtBlood(this.attack, this);//攻击敌人
                                TipsTxtManager.single.showCombatTxt("二连击", cc.v2(this.node.x, this.node.y + this.node.height * 0.5),
                                    this.node.parent, cc.Color.BLUE);
                            }
                        }
                        if (SkillManager.single.isUnlockSkill(SkillIdCenter.id_1014)) {
                            var ey = SkillManager.single.getSkillEntity(SkillIdCenter.id_1014);
                            var random = randomRange(1, 10000);
                            if (random <= ey.valueNum * 100) {
                                otherEle.hurtBlood(this.attack, this);//攻击敌人
                                otherEle.hurtBlood(this.attack, this);
                                TipsTxtManager.single.showCombatTxt("三连击", cc.v2(this.node.x, this.node.y + this.node.height * 0.5),
                                    this.node.parent, cc.Color.BLUE);
                            }
                        }
                    }

                    this.scheduleOnce(() => {
                        this.collider2d.enabled = true;
                    });
                }
                this.changeState(this.attackState);
            }




        }
    }
    onEndContact(contact, selfCollider: cc.Collider, otherCollider: cc.Collider): void {
        // console.log("离开碰撞");
        if (otherCollider.tag == 101) {//撞到左右柱子
            return;
        }
        var otherEle = otherCollider.getComponent(BaseCharacterElement);
        if (otherEle != null) {
            if (!otherEle.isDead()) {
                this.changeState(this.idleState);
                this.isCollidePlatform = false;
            } else {
                this.changeState(this.runState);
                this.isCollidePlatform = true;
            }
        } else {
            this.changeState(this.idleState);
            this.isCollidePlatform = false;
            if (!this.isApplyLinearImpulse) {
                this.rb2d.linearVelocity = cc.Vec2.ZERO;
            }
        }
    }


    protected update(dt: number): void {
        if (!CombatComponent.startCombat) {
            return;
        }
        this.currentState.UpdataState(dt);
        if (this.hurtBloodCd > 0) {
            this.hurtBloodCd -= dt;
        }
    }
    public initState(): void {
        this.currentState = this.idleState;
        this.currentState.EnterState();
    }
    buildData(ey: CharacterEntity) {
        this.characterEy = ey;
        this.attribute.maxHealth = this.characterEy.health;
        this.attribute.attack = this.characterEy.attack;
        this.attribute.critical = this.characterEy.critical;
        this.attribute.criticalDamage = this.characterEy.criticalDamage;
        this.attribute.moveSpeed = this.characterEy.moveSpeed;
        this.collider2d.density = this.characterEy.density;

        this.currentHealth = this.maxHealth;
        this.drawHp();
    }


    public changeState(newState: BaseState): void {
        this.currentState.ExitState();
        this.currentState = newState;
        this.currentState.EnterState();
    }
    public changeDirection(pos: cc.Vec2): void {
        if (this.node.x < pos.x) {
            this.changeRightDir();
        } else if (this.node.x > pos.x) {
            this.changeLeftDir();
        }
    }
    public changeRightDir() {
        if (this.direction == CharacterDirection.left) {
            this.node.scaleX = 1;
            this.hpTxt.node.scaleX = 1;
            this.hpProgressbar.node.scaleX = 0.5;
            this.direction = CharacterDirection.right;
        }

    }
    public changeLeftDir() {
        if (this.direction == CharacterDirection.right) {
            this.node.scaleX = -1;
            this.hpTxt.node.scaleX = -1;
            this.hpProgressbar.node.scaleX = -0.5;
            this.direction = CharacterDirection.left;
        }
    }

    public getPathPosArr(): cc.Vec2[] {
        var combatComp = this.node.parent.getComponent(CombatComponent);
        var posArr: cc.Vec2[] = [];
        if (combatComp != null) {
            let arr: cc.Node[] = combatComp.pathList;
            if (GameManager.single.gameModel == GameModel.FuBenModel) {
                arr = combatComp.fubenPathList;
            }
            for (let i = 0; i < arr.length; i++) {
                posArr[i] = cc.v2(arr[i].x, arr[i].y);
            }
        }

        return posArr;
    }

    isBaoJi(): boolean {
        var random = randomRange(1, 10000);
        return random <= this.critical;
    }

    public get currentHealth(): number {
        return this.attribute.currentHealth;
    }
    public set currentHealth(value: number) {
        this.attribute.currentHealth = value;
    }

    public get maxHealth(): number {
        return this.attribute.maxHealth;
    }

    public get attack(): number {
        return Math.ceil(this.attribute.attack);
    }
    public get critical(): number {
        return this.attribute.critical;
    }
    public get criticalDamage(): number {
        return this.attribute.criticalDamage;
    }

    public get moveSpeed(): number {
        var speed = this.attribute.moveSpeed;
        if (CardManager.single.isHavePerpetualCard()) {
            speed *= (SaveManager.single.userdata.addSpeedMode + 1);
        }

        return speed;
    }

    public hurtBlood(ack: number, acker: BaseCharacterElement) {
        if (this.isDead()) {
            return;
        }
        var ackNum = ack;
        if (acker != null && acker.isBaoJi()) {
            ackNum *= Math.ceil(acker.criticalDamage * 0.01);
        }
        if (this.characterType == CharacterType.enemy) {//敌人受到伤害
            TaskManager.single.requestUpdataTaskPregress(110, Math.ceil(ackNum));
        }
        // if (CC_DEBUG) {

        // } else {
        this.currentHealth -= ackNum;
        // }

        this.drawHp();
        var posx = randomRange(this.node.x - 50, this.node.x + 50);
        TipsTxtManager.single.showCombatTxt(ackNum.toString(), cc.v2(posx, this.node.y + this.node.height * 0.5), this.node.parent);

        if (acker != null && acker.characterType == CharacterType.player) {
            if (SkillManager.single.isUnlockSkill(SkillIdCenter.id_1015)) {
                var ey = SkillManager.single.getSkillEntity(SkillIdCenter.id_1015);
                if (this.currentHealth / this.maxHealth <= 0.15 && randomRange(1, 10000) <= ey.valueNum * 100) {
                    this.currentHealth = 0;
                    TipsTxtManager.single.showCombatTxt("必杀一击", cc.v2(acker.node.x, acker.node.y + acker.node.height * 0.5),
                        this.node.parent, cc.Color.BLUE);
                }
            }
        }

        if (this.currentHealth <= 0) {
            this.currentHealth = 0;
            if (this.characterType == CharacterType.player) {
                if (SkillManager.single.isUnlockSkill(SkillIdCenter.id_1012)) {
                    var ey = SkillManager.single.getSkillEntity(SkillIdCenter.id_1012);
                    var random = randomRange(1, 10000);
                    if (random <= ey.valueNum * 100) {
                        this.currentHealth = this.maxHealth;
                        return;
                    }
                }
            }


            this.deadToDo();
            this.callDead();

        }

    }
    /**
     * 死亡处理
     */
    deadToDo() {
        this.changeState(this.idleState);
        this.rb2d.linearVelocity = cc.v2();
        this.pathIndex = 1;
        PoolManager.single.returnNode(this.characterEy.characterTp.resName, this.node);

    }
    callDead() {
        if (this.characterType == CharacterType.enemy) {
            GameEvent.eventNode.emit(GameEvent.DEADENEMY_EVENT, this.characterEy);
        }
    }
    isDead(): boolean {
        return this.currentHealth <= 0;

    }

    drawHp() {
        this.hpTxt.string = "" + this.currentHealth;
        this.hpProgressbar.progress = this.currentHealth / this.maxHealth;
    }

    hitClick() {
        //console.log("hitClick");
        if (this.isDead()) {
            return;
        }
        // if (CC_DEBUG) {
        //     this.hurtBlood(1000, null);
        // } else {
        this.hurtBlood(SaveManager.single.userdata.hitAttack, null);
        // }

        // AudioManager.single.playEffect(AudioEffectType.hit);
        var userdata = SaveManager.single.userdata;
        if (userdata.guideId == 1) {
            SaveManager.single.updataGuideId();
        }
    }

}
